/*!
   \file

   © 2011 Mark W. Gabby II

   This file is part of the Avion engine.

   The Avion engine is free software: you can redistribute it and/or modify it under the terms of
   the GNU General Public License as published by the Free Software Foundation, either version 3 of
   the License, or (at your option) any later version.

   The Avion engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
   the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along with the Avion Engine.
   If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>

#include "Systems/Constants/InputTypes.hpp"
#include "Util/GlobalConstants.hpp"

typedef uint16_t tPixelFormatIndex;
const tPixelFormatIndex kNullPixelFormatIndex = kNull16;
typedef uint16_t tScreenModeIndex;
const tScreenModeIndex kNullScreenModeIndex = kNull16;
typedef uint8_t tControllerIndex;
const tControllerIndex kNullControllerIndex = kNull8;
typedef uint8_t tMonitorIndex;
const tMonitorIndex kNullMonitorIndex = kNull8;
typedef uint8_t tWindowID;
const tMonitorIndex kNullWindowID = kNull8;

typedef void ( *tSendInputMessage )( const InputMessage & Message );
typedef void ( *tControllerCaptured )( const bool AxesAvailable[kMaxControllerAxes] );
typedef void ( *tControllerReleased )( void );
typedef void ( *tSetModifierState )( const eKeyInput Key, const bool Down );

typedef void ( *tAddGraphicsViewport )( const tWindowID WindowID,
                                        const uint16_t Width, const uint16_t Height,
                                        const float FOVDegrees, const float AspectRatio );

enum eAccelerationTypes
{
   kInvalid,
   kFull,
   kPartial,
   kNone
};

enum eMessageTypes
{
   kWarningMessage,
   kErrorMessage,
   kInformationMessage
};

enum eMessageOptions
{
   kConfirm,
   kConfirmCancel,
   kYesNo,
   kYesNoCancel,
   kRetryCancel,
   kCancelRetryContinue
};

enum eMessageResults
{
   kMessageConfirm,
   kMessageYes,
   kMessageNo,
   kMessageCancel,
   kMessageContinue,
   kMessageRetry
};

/*!
    \brief
    This structure contains information about monitors attached to the system.
*/
struct MonitorInfo
{
   bool valid;
   bool primary;

   std::string name;
   std::string string;
};

struct ScreenSettings
{
   tMonitorIndex MonitorIndex;
   tScreenModeIndex ModeIndex;
   tPixelFormatIndex PixelFormatIndex;

   uint16_t Width;
   uint16_t Height;

   int16_t OffsetX;
   int16_t OffsetY;

   float AspectRatio;
   float FOVDegrees;
};

/*!
    \brief
    This structure contains information
    about different screen formats that
    the operating system can display in
    a window.
*/
struct ScreenModeInfo
{
   void MakeNull()
   {
      dimensions[kWidth] = kNull32;
      dimensions[kHeight] = kNull32;
      bitsPerPixel = kNull8;
      refreshRate = kNull32;
   }
   bool IsNull()
   {

      if ( ( dimensions[kWidth] == kNull32 ) &&
            ( dimensions[kHeight] == kNull32 ) &&
            ( bitsPerPixel == kNull8 ) &&
            ( refreshRate == kNull32 ) )
      {
         return true;
      }

      return false;
   }

   uint32_t dimensions[2];
   uint8_t bitsPerPixel;
   uint32_t refreshRate;
};

/*!
    \brief
    This structure contains information
    about different pixel, depth, and
    other buffer bit depths, and
    multisample antialiasing supported
    in each mode.
*/
struct PixelFormat
{
   PixelFormat()
   {
      MakeNull();
   }

   void MakeNull()
   {
      bitPerColor[kR] = kNull8;
      bitPerColor[kG] = kNull8;
      bitPerColor[kB] = kNull8;
      bitPerColor[kA] = kNull8;

      bitsPerPixel = kNull8;

      depthBufferBits = kNull8;
      accumBufferBits = kNull8;
      stencilBits = kNull8;
      multisampleMode = kNull8;

      doubleBuffered = false;
      glWindowSupported = false;
      RGBA = false;

      acceleration = kInvalid;
   }
   bool IsNull()
   {
      if ( ( bitPerColor[kR] == kNull8 ) &&
           ( bitPerColor[kG] == kNull8 ) &&
           ( bitPerColor[kB] == kNull8 ) &&
           ( bitPerColor[kA] == kNull8 ) &&

           ( bitsPerPixel == kNull8 ) &&

           ( depthBufferBits == kNull8 ) &&
           ( accumBufferBits == kNull8 ) &&
           ( stencilBits == kNull8 ) &&
           ( multisampleMode == kNull8 ) &&

           ( doubleBuffered == false ) &&
           ( glWindowSupported == false ) &&
           ( RGBA == false ) &&

           ( acceleration == kInvalid ) )
      {
         return true;
      }

      return false;
   }

   uint8_t bitPerColor[4];
   uint8_t bitsPerPixel;

   uint8_t depthBufferBits;
   uint8_t accumBufferBits;
   uint8_t stencilBits;
   uint8_t multisampleMode;

   bool doubleBuffered;
   bool glWindowSupported;
   bool RGBA;

   eAccelerationTypes acceleration;
};

struct ControllerInfo
{
   uint8_t NumButtons;
   uint8_t NumAxes; // A "throttle" is just an axis.
   bool Hat; // Does this controller have a hat switch?
};
